package com.iwomy.envpro.platform.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.iwomy.envpro.admin.api.entity.SysDept;
import com.iwomy.envpro.admin.api.entity.SysTenant;
import com.iwomy.envpro.admin.api.feign.RemoteDeptService;
import com.iwomy.envpro.admin.api.feign.RemoteTenantService;
import com.iwomy.envpro.common.core.constant.SecurityConstants;
import com.iwomy.envpro.common.core.util.R;
import com.iwomy.envpro.common.data.datascope.DataScope;
import com.iwomy.envpro.common.data.tenant.TenantContextHolder;
import com.iwomy.envpro.common.security.util.SecurityUtils;
import com.iwomy.envpro.platform.VO.AirMonitorEquipmentDetailVO;
import com.iwomy.envpro.platform.VO.AirMonitorEquipmentVO;
import com.iwomy.envpro.platform.VO.EquipmentOnlineStatusVO;
import com.iwomy.envpro.platform.constant.DeviceStatusConstants;
import com.iwomy.envpro.platform.constant.RedisConstants;
import com.iwomy.envpro.platform.dto.AirMonitorEquipmentDTO;
import com.iwomy.envpro.platform.dto.CommandCodeDTO;
import com.iwomy.envpro.platform.entity.*;
import com.iwomy.envpro.platform.handler.EPServerHandler;
import com.iwomy.envpro.platform.mapper.AirMonitorEquipmentMapper;
import com.iwomy.envpro.platform.service.*;
import com.iwomy.envpro.platform.utils.DeptFillUtils;
import com.iwomy.envpro.platform.utils.RedisClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 监测设备管理
 *
 * @author pig
 * @date 2023-08-28 10:12:58
 */
@Service
@Slf4j
public class AirMonitorEquipmentServiceImpl extends ServiceImpl<AirMonitorEquipmentMapper, AirMonitorEquipmentEntity> implements AirMonitorEquipmentService {
	@Resource
	private AirSiteService airSiteService;
	@Resource
	private DataTemplateDetailsService dataTemplateDetailsService;
	@Resource
	private AirFactorService airFactorService;
	@Resource
	private RedisClient redisClient;
	@Resource
	private AlarmLoggingService alarmLoggingService;
	@Resource
	private RemoteTenantService remoteTenantService;
	@Resource
	private RemoteDeptService remoteDeptService;
	@Resource
	private BasicEquipmentCalibrationRecordService equipmentCalibrationRecordService;

	@Override
	public Page<AirMonitorEquipmentEntity> getAirMonitorEquipmentList(Page page, Long id) {
		Page airSiteList = airSiteService.getAirSitePage(new Page(), id);
		List<AirSiteEntity> records = airSiteList.getRecords();
		List<Long> airSiteIds = records.stream().map(AirSiteEntity::getId).collect(Collectors.toList());

		if (ObjectUtil.isEmpty(airSiteIds)) return new Page();

		LambdaQueryWrapper<AirMonitorEquipmentEntity> queryWrapper = Wrappers.<AirMonitorEquipmentEntity>lambdaQuery();
		return this.getBaseMapper().selectPage(page, queryWrapper.in(AirMonitorEquipmentEntity::getAirSiteId, airSiteIds));
	}

	@Override
	public AirMonitorEquipmentEntity selectOneByEquipmentId(String equipment_id) {
		LambdaQueryWrapper<AirMonitorEquipmentEntity> eq = Wrappers.<AirMonitorEquipmentEntity>lambdaQuery().eq(AirMonitorEquipmentEntity::getEquipmentCode, equipment_id);
		return getOne(eq);
	}

	@Override
	public List<AirMonitorEquipmentEntity> selectListByStatus(Integer status) {
		LambdaQueryWrapper<AirMonitorEquipmentEntity> eq = Wrappers.<AirMonitorEquipmentEntity>lambdaQuery().eq(AirMonitorEquipmentEntity::getStatus, status);
		return list(eq);
	}

	@Override
	public List<AirMonitorEquipmentEntity> listByTag(AirMonitorEquipmentDTO airMonitorEquipmentDTO) {
		List<AirSiteEntity> airSiteList = airSiteService.getAirSiteList(airMonitorEquipmentDTO.getTag());
		List<Long> airSiteIds = airSiteList.stream().map(AirSiteEntity::getId).collect(Collectors.toList());
		LambdaQueryWrapper<AirMonitorEquipmentEntity> queryWrapper = Wrappers.<AirMonitorEquipmentEntity>lambdaQuery();

		if (ObjectUtil.isEmpty(airSiteIds) && StrUtil.isEmpty(airMonitorEquipmentDTO.getEquipmentCodeLike()))
			return new ArrayList<>();

		if (StrUtil.isNotEmpty(airMonitorEquipmentDTO.getEquipmentCodeLike())) {
			queryWrapper.like(AirMonitorEquipmentEntity::getEquipmentCode, airMonitorEquipmentDTO.getEquipmentCodeLike());
		}
		if (ObjectUtil.isNotNull(airSiteIds)) {
			queryWrapper.in(AirMonitorEquipmentEntity::getAirSiteId, airSiteIds);
		}
		List<Long> data = remoteDeptService.listByDeptId(SecurityUtils.getUser().getDeptId()).getData();
		queryWrapper.in(AirMonitorEquipmentEntity::getDeptId, data);

		return this.getBaseMapper().selectList(queryWrapper);
	}

	@Override
	public Page<AirMonitorEquipmentVO> getAirMonitorEquipmentPage(Page<AirMonitorEquipmentVO> page, AirMonitorEquipmentDTO airMonitorEquipmentDTO) {
		List<AirSiteEntity> airSiteList = airSiteService.getAirSiteList(airMonitorEquipmentDTO.getTag());
		List<Long> airSiteIds = airSiteList.stream().map(AirSiteEntity::getId).collect(Collectors.toList());

		if (ObjectUtil.isEmpty(airSiteIds) && ObjectUtil.isNotNull(airMonitorEquipmentDTO.getTag()))
			return page;

		LambdaQueryWrapper<AirMonitorEquipmentEntity> queryWrapper = Wrappers.lambdaQuery();

		queryWrapper.in(ObjectUtil.isNotEmpty(airSiteList),AirMonitorEquipmentEntity::getAirSiteId, airSiteIds);
		List<AirMonitorEquipmentEntity> list = this.baseMapper.selectListByScope(queryWrapper, new DataScope());
		List<Long> equipmentId = list.stream().map(AirMonitorEquipmentEntity::getId).collect(Collectors.toList());
		if (ObjectUtil.isEmpty(equipmentId)) return page;
		MPJLambdaWrapper<AirMonitorEquipmentEntity> wrapper = new MPJLambdaWrapper<>();
		wrapper.selectAll(AirMonitorEquipmentEntity.class)

				.selectAs(AirGridMemberEntity::getName, AirMonitorEquipmentVO::getGridMemberName)
				.selectAs(AirSiteEntity::getName, AirMonitorEquipmentVO::getAirSiteName)
				.selectAs(BasicEquipmentModelEntity::getName, AirMonitorEquipmentVO::getEquipmentModelName)
				.selectAs(BasicEquipmentTypeEntity::getTypeName, AirMonitorEquipmentVO::getEquipmentTypeName)

				.leftJoin(AirGridMemberEntity.class, AirGridMemberEntity::getId, AirMonitorEquipmentEntity::getGridMemberId)
				.leftJoin(AirSiteEntity.class, AirSiteEntity::getId, AirMonitorEquipmentEntity::getAirSiteId)
				.leftJoin(BasicEquipmentModelEntity.class, BasicEquipmentModelEntity::getId, AirMonitorEquipmentEntity::getEquipmentModelId)
				.leftJoin(BasicEquipmentTypeEntity.class, BasicEquipmentTypeEntity::getId, AirMonitorEquipmentEntity::getEquipmentTypeId);

		wrapper.in(AirMonitorEquipmentEntity::getId, equipmentId);
		wrapper.like(StrUtil.isNotEmpty(airMonitorEquipmentDTO.getEquipmentCodeLike()), AirMonitorEquipmentEntity::getEquipmentCode, airMonitorEquipmentDTO.getEquipmentCodeLike());
		wrapper.like(StrUtil.isNotEmpty(airMonitorEquipmentDTO.getEquipmentNameLike()), AirMonitorEquipmentEntity::getName, airMonitorEquipmentDTO.getEquipmentNameLike());
		wrapper.like(StrUtil.isNotEmpty(airMonitorEquipmentDTO.getAirSiteNameLike()), AirSiteEntity::getName, airMonitorEquipmentDTO.getAirSiteNameLike());
//		wrapper.in(ObjectUtil.isNotEmpty(airSiteIds), AirMonitorEquipmentEntity::getAirSiteId, airSiteIds);
		wrapper.eq(ObjectUtil.isNotNull(airMonitorEquipmentDTO.getStatus()), AirMonitorEquipmentEntity::getStatus, airMonitorEquipmentDTO.getStatus());
		if (ObjectUtil.isNotEmpty(airMonitorEquipmentDTO.getDeptId())) {
			List<Long> data = remoteDeptService.listByDeptId(airMonitorEquipmentDTO.getDeptId()).getData();
			wrapper.in(AirMonitorEquipmentEntity::getDeptId, data);
		}
		page = this.getBaseMapper().selectJoinPage(page, AirMonitorEquipmentVO.class, wrapper);
		if (ObjectUtil.isNull(page)) return new Page<>();
		DeptFillUtils.fill(page);
		return page;
	}

	@Override
	public void atCommand(CommandCodeDTO commandCodeDTO) {
		EPServerHandler.sendCommand(commandCodeDTO.getEquipmentCode(), commandCodeDTO.getConfigContent());
	}

	@Override
	public String config(CommandCodeDTO commandCodeDTO) {
		String configType = commandCodeDTO.getConfigType();
		String equipmentCode = commandCodeDTO.getEquipmentCode();
		String configContent = commandCodeDTO.configContent;

		if (configType.equals("1001") || configType.equals("1002") || configType.equals("1003") || configType.equals("1004")) {
			return this.sendAtConfigWrite2Device(equipmentCode, configType, configContent);
		} else if (configType.equals("2001") || configType.equals("2002") || configType.equals("2003") || configType.equals("2004")) {
			this.send212ConfigWrite2Device(equipmentCode, "123456", configType, configContent);
		}

		BasicEquipmentCalibrationRecordEntity calibrationRecord = new BasicEquipmentCalibrationRecordEntity();
		calibrationRecord.setEquipmentCode(equipmentCode);
		calibrationRecord.setConfigType(configType);
		String[] values = configContent.split(";");
		calibrationRecord.setFactorCode(values[0].trim());
		calibrationRecord.setRegisterStartAddress(values[1].trim());
		calibrationRecord.setCalibratingValue(values[2].trim());
		calibrationRecord.setTenantId(SecurityUtils.getUser().getTenantId());
		calibrationRecord.setFactorName(commandCodeDTO.getCnName());
		equipmentCalibrationRecordService.save(calibrationRecord);

		return "";
	}

	@Override
	public List<AirFactorEntity> getMonitorEquipmentFactor(Long monitorEquipmentId) {

		AirMonitorEquipmentEntity airMonitorEquipmentEntity = this.getById(monitorEquipmentId);

		List<DataTemplateDetailsEntity> dataTemplateDetailsEntities = dataTemplateDetailsService.listByDataTemplateId(airMonitorEquipmentEntity.getDataTemplateId());

		if (ObjectUtil.isEmpty(dataTemplateDetailsEntities)) return null;

		List<Long> factorList = dataTemplateDetailsEntities.stream().map(DataTemplateDetailsEntity::getFactorId).collect(Collectors.toList());


		return airFactorService.listByIds(factorList);
	}

	@Override
	public EquipmentOnlineStatusVO onlineStatus(AirMonitorEquipmentDTO airMonitorEquipmentDTO) {

		List<AirSiteEntity> airSiteList = airSiteService.getAirSiteList(airMonitorEquipmentDTO.getTag());
		List<Long> airSiteIds = airSiteList.stream().map(AirSiteEntity::getId).collect(Collectors.toList());

		EquipmentOnlineStatusVO equipmentOnlineStatusVO = new EquipmentOnlineStatusVO();
		//tag为空则是搜索全部
		if (ObjectUtil.isEmpty(airSiteIds) && ObjectUtil.isNotNull(airMonitorEquipmentDTO.getTag()))
			return equipmentOnlineStatusVO;


		MPJLambdaWrapper<AirMonitorEquipmentEntity> wrapper = new MPJLambdaWrapper<>();
		wrapper.select(AirMonitorEquipmentEntity::getId)
				.leftJoin(AirGridMemberEntity.class, AirGridMemberEntity::getId, AirMonitorEquipmentEntity::getGridMemberId)
				.leftJoin(AirSiteEntity.class, AirSiteEntity::getId, AirMonitorEquipmentEntity::getAirSiteId)
				.leftJoin(BasicEquipmentModelEntity.class, BasicEquipmentModelEntity::getId, AirMonitorEquipmentEntity::getEquipmentModelId)
				.leftJoin(BasicEquipmentTypeEntity.class, BasicEquipmentTypeEntity::getId, AirMonitorEquipmentEntity::getEquipmentTypeId)
		;
		wrapper.eq(AirMonitorEquipmentEntity::getTenantId, TenantContextHolder.getTenantId());
		if (StrUtil.isNotEmpty(airMonitorEquipmentDTO.getEquipmentCodeLike())) {
			wrapper.like(AirMonitorEquipmentEntity::getEquipmentCode, airMonitorEquipmentDTO.getEquipmentCodeLike());
		}
		if (StrUtil.isNotEmpty(airMonitorEquipmentDTO.getEquipmentNameLike())) {
			wrapper.like(AirMonitorEquipmentEntity::getName, airMonitorEquipmentDTO.getEquipmentNameLike());
		}
		if (StrUtil.isNotEmpty(airMonitorEquipmentDTO.getAirSiteNameLike())) {
			wrapper.like(AirSiteEntity::getName, airMonitorEquipmentDTO.getAirSiteNameLike());
		}
		if (ObjectUtil.isNotEmpty(airSiteIds)) {
			wrapper.in(AirMonitorEquipmentEntity::getAirSiteId, airSiteIds);
		}
		if (ObjectUtil.isNotNull(airMonitorEquipmentDTO.getStatus())) {
			wrapper.eq(AirMonitorEquipmentEntity::getStatus, airMonitorEquipmentDTO.getStatus());
		}
		List<Long> data = remoteDeptService.listByDeptId(SecurityUtils.getUser().getDeptId()).getData();
		wrapper.in(AirMonitorEquipmentEntity::getDeptId, data);
		long total = this.count(wrapper);
		wrapper.eq(AirMonitorEquipmentEntity::getStatus, DeviceStatusConstants.DEVICE_OFFLINE);
		long offline = this.count(wrapper);

		long online = total - offline;
		equipmentOnlineStatusVO.setTotal(total);
		equipmentOnlineStatusVO.setOnline(online);
		equipmentOnlineStatusVO.setOffline(offline);
		return equipmentOnlineStatusVO;
	}

	@Override
	public AirMonitorEquipmentDetailVO getDetailById(Long getDetailById) {
		MPJLambdaWrapper<AirMonitorEquipmentEntity> wrapper = new MPJLambdaWrapper<>();
		wrapper.selectAll(AirMonitorEquipmentEntity.class)
				.selectAs(AirGridMemberEntity::getName, AirMonitorEquipmentDetailVO::getGridMemberName)
				.selectAs(AirSiteEntity::getName, AirMonitorEquipmentDetailVO::getAirSiteName)
				.selectAs(BasicEquipmentModelEntity::getName, AirMonitorEquipmentDetailVO::getEquipmentModelName)
				.selectAs(BasicEquipmentTypeEntity::getTypeName, AirMonitorEquipmentDetailVO::getEquipmentTypeName)

				.leftJoin(AirGridMemberEntity.class, AirGridMemberEntity::getId, AirMonitorEquipmentEntity::getGridMemberId)
				.leftJoin(AirSiteEntity.class, AirSiteEntity::getId, AirMonitorEquipmentEntity::getAirSiteId)
				.leftJoin(BasicEquipmentModelEntity.class, BasicEquipmentModelEntity::getId, AirMonitorEquipmentEntity::getEquipmentModelId)
				.leftJoin(BasicEquipmentTypeEntity.class, BasicEquipmentTypeEntity::getId, AirMonitorEquipmentEntity::getEquipmentTypeId)
				.eq(AirMonitorEquipmentEntity::getId, getDetailById);
		AirMonitorEquipmentDetailVO airMonitorEquipmentDetailVO = this.getBaseMapper().selectJoinOne(AirMonitorEquipmentDetailVO.class, wrapper);
		Optional.ofNullable(airMonitorEquipmentDetailVO).filter(x -> x.getAlarmStatus() == 2).ifPresent(x -> {
			LambdaQueryWrapper<AlarmLoggingEntity> alarmLoggingWrappers = Wrappers.lambdaQuery();
			alarmLoggingWrappers.eq(AlarmLoggingEntity::getEquipmentId, getDetailById)
					.eq(AlarmLoggingEntity::getEventStatus, 10)
					.orderByDesc(AlarmLoggingEntity::getCreateTime)
					.last("limit 1");
			AlarmLoggingEntity one = alarmLoggingService.getOne(alarmLoggingWrappers);
			Optional.ofNullable(one).ifPresent(alarmLoggingEntity -> {
				airMonitorEquipmentDetailVO.setAlarmTime(alarmLoggingEntity.getCreateTime());
			});

		});

		return airMonitorEquipmentDetailVO;
	}

	@Override
	public R newlyAdded(AirMonitorEquipmentEntity airMonitorEquipment) {


		R<SysTenant> details = remoteTenantService.details(TenantContextHolder.getTenantId(), SecurityConstants.FROM_IN);
		SysTenant sysTenant = details.getData();

		Long count = this.count();

		long residueDevice = Optional.ofNullable(sysTenant.getDeviceTotal() - count).orElse(0l);
		if (residueDevice < 1) {
			return R.failed("设备已达上限");
		}

		Long tenantId = TenantContextHolder.getTenantId();
		AirMonitorEquipmentEntity wrapperEntity = new AirMonitorEquipmentEntity();
		wrapperEntity.setEquipmentCode(airMonitorEquipment.getEquipmentCode());
		LambdaQueryWrapper<AirMonitorEquipmentEntity> wrapper = Wrappers.lambdaQuery(wrapperEntity);

		TenantContextHolder.clear();
		AirMonitorEquipmentEntity one = this.getOne(wrapper);

		TenantContextHolder.setTenantId(tenantId);
		//TODO 控制并发加锁  或者用消息队列
		if (ObjectUtil.isNotNull(one)) {
			return R.failed("设备编号已存在");
		}
		sysTenant.setUsedDevice(count.intValue() + 1);
//		airMonitorEquipment.setDeptId(SecurityUtils.getUser().getDeptId());


		this.save(airMonitorEquipment);


		remoteTenantService.update(sysTenant, SecurityConstants.FROM_IN);
		return R.ok();
	}

	@Override
	public boolean remove(Long[] ids) {
		//TODO 控制并发加锁  或者用消息队列
//		List<Long> longs = CollUtil.toList(ids);
		R<SysTenant> details = remoteTenantService.details(TenantContextHolder.getTenantId(), SecurityConstants.FROM_IN);
		SysTenant sysTenant = details.getData();
		this.removeBatchByIds(CollUtil.toList(ids));
		Long count = this.count();
		sysTenant.setUsedDevice(count.intValue());
		remoteTenantService.update(sysTenant, SecurityConstants.FROM_IN);
		return true;
	}

	@Override
	public List<AirMonitorEquipmentEntity> pageByScope(AirMonitorEquipmentEntity airMonitorEquipment) {
		List data = remoteDeptService
				.listByDeptId(ObjectUtil.isNull(airMonitorEquipment.getDeptId()) ?
						SecurityUtils.getUser().getDeptId() : airMonitorEquipment.getDeptId()).getData();
		airMonitorEquipment.setDeptId(null);
		LambdaQueryWrapper<AirMonitorEquipmentEntity> queryWrapper = Wrappers.lambdaQuery(airMonitorEquipment);
		queryWrapper.in(ObjectUtil.isNotEmpty(data), AirMonitorEquipmentEntity::getDeptId, data);
		List<AirMonitorEquipmentEntity> airMonitorEquipmentEntities = this.getBaseMapper().selectListByScope(queryWrapper, new DataScope());
		return airMonitorEquipmentEntities;
	}


	public static void main(String[] args) {
		LocalDateTime now = LocalDateTime.now();
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
		String formattedDateTime = now.format(formatter);
		String data = "QN=" + formattedDateTime + ";ST=27;CN=2031;PW=123456;MN=20230613000002;Flag=5;CP=&&BeginTime=20231007000000;EndTime=20231007000000&&"; // 要计算CRC的数据
//			String data = "QN=20160801085857223;ST=32;CN=1062;PW=100000;MN=010000A8900016F000169DC0;Flag=5;CP=&&RtdInterval=30&&"; // 要计算CRC的数据
//			String data="QN=20230928184016000;ST=27;CN=2011;PW=123456;MN=20230613000002;Flag=4;CP=&&DataTime=20230928184016;a21026-Rtd=34,a21026-Flag=N;a21005-Rtd=0.507,a21005-Flag=N;a21004-Rtd=34,a21004-Flag=N;a80218-Rtd=45,a80218-Flag=N;aa0002-Rtd=2.040,aa0002-Flag=N;a34004-Rtd=33,a34004-Flag=N;a34002-Rtd=35,a34002-Flag=N;a01001-Rtd=22.3,a01001-Flag=N;a01002-Rtd=91.9,a01002-Flag=N;a01007-Rtd=1.04,a01007-Flag=N;a01008-Rtd=196,a01008-Flag=N;a01006-Rtd=958.7,a01006-Flag=N;aa0004-Rtd=94,aa0004-Flag=N&&";
		// 计算CRC校验值
		String crcHex = crc16(data, data.length());

		// 将CRC校验值转换为16进制字符串

		// 输出CRC校验值
		System.out.println("CRC校验值：\n" + "##0" + data.length() + data + crcHex + "\r\n1");
	}

	public static String crc16(String src, int len) {
		int crc = 0x0000FFFF;
		short tc;
		char sbit;
		for (int i = 0; i < len; i++) {
			tc = (short) (crc >>> 8);
			crc = ((tc ^ src.charAt(i)) & 0x00FF);
			for (int r = 0; r < 8; r++) {
				sbit = (char) (crc & 0x01);
				crc >>>= 1;
				if (sbit != 0)
					crc = (crc ^ 0xA001) & 0x0000FFFF;
			}
		}
		String str = Integer.toHexString(crc);
		if (str.length() == 3) {
			return "0" + str.toUpperCase();
		} else if (str.length() == 2) {
			return "00" + str.toUpperCase();
		} else if (str.length() == 1) {
			return "000" + str.toUpperCase();
		}
		return str.toUpperCase();
	}


	public String sendAtConfigWrite2Device(String _iDeviceId, String _iConfigType, String _iConfigContent) {
		log.info("{},进入配置", _iDeviceId);
		EPServerHandler.sendCommand(_iDeviceId, "***COMMIT CONFIG***");
		if (_iConfigType.equals("1002")) {
			//显示配置
			EPServerHandler.sendCommand(_iDeviceId, "AT+SHOW\n");

			ThreadUtil.sleep(5000);

			Set<Object> members = redisClient.members(RedisConstants.ENVPRO_DEVICS_CONFIG_KEY + _iDeviceId);
			redisClient.del(RedisConstants.ENVPRO_DEVICS_CONFIG_KEY + _iDeviceId);
			return ArrayUtil.join(members, ",");

		} else if (!_iConfigType.equals("1003")) {
			if (_iConfigType.equals("1004")) {
				EPServerHandler.sendCommand(_iDeviceId, "AT+RESET\n");
				//重启设备
			}
		} else {
			//保存配置
			String[] _iConfigContentArr = _iConfigContent.split(";");
			for (int i = 0; i < _iConfigContentArr.length; i++) {
				String tempCommand = _iConfigContentArr[i] + "\r\n";
				EPServerHandler.sendCommand(_iDeviceId, tempCommand);
			}
		}
		return "";
	}

	public void send212ConfigWrite2Device(String _iDeviceId, String _iPW, String _iConfigType, String _iConfigContent) {
		if (_iConfigType.equals("2001")) {
			if (_iConfigContent.startsWith("AT+RMTUPGRADE")) {
				EPServerHandler.sendCommand(_iDeviceId, this.deviceRemoteSetResponse(_iDeviceId, _iPW, _iConfigContent));
				return;
			}
			String _iConfigContent2 = _iConfigContent.replace(";", "\r\n");
			if (!_iConfigContent2.endsWith("\r\n")) {
				_iConfigContent2 = _iConfigContent2 + "\r\n";
			}
			EPServerHandler.sendCommand(_iDeviceId, this.deviceRemoteSetResponse(_iDeviceId, _iPW, _iConfigContent2));
		} else if (_iConfigType.equals("2002")) {
			String[] commandArr = _iConfigContent.split(";");
			String RlyNum = commandArr[0];
			String RlyVal = commandArr[1];
			EPServerHandler.sendCommand(_iDeviceId, this.relaySwitchControlResponse(_iDeviceId, _iPW, RlyNum, RlyVal));
		} else if (_iConfigType.equals("2003")) {
			EPServerHandler.sendCommand(_iDeviceId, this.DeviceRemoteSetCalibration(_iDeviceId, _iPW, _iConfigContent));
		} else if (_iConfigType.equals("2004")) {
			EPServerHandler.sendCommand(_iDeviceId, this.deviceRemoteSetResponse(_iDeviceId, _iPW, "AT+RESET\n"));
		}
	}

	private static String getQN() {
		LocalDateTime now = LocalDateTime.now();
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
		return now.format(formatter);
	}

	public static String deviceRemoteSetResponse(String MN, String PW, String commandStr) {
		String QN = getQN();
		String responseData = "QN=" + QN + ";ST=91;CN=9050;PW=" + PW + ";MN=" + MN + ";Flag=5;CP=&&" + commandStr + "&&";
		int responseDataLength = responseData.length();
		DecimalFormat df = new DecimalFormat("0000");
		String responseDataLength4 = df.format(responseDataLength);
		String crc16 = crc16(responseData, responseData.length());
//		String crc16 = CrcUtil.CRC16_212(responseData.getBytes());
		if (crc16.length() < 4) {
			crc16 = String.format("%4s", crc16).replace(' ', '0');
		}
		String responseMsg = "##" + responseDataLength4 + responseData + crc16.toUpperCase() + "\r\n";
		log.info("device remote set response：" + responseMsg);
		return responseMsg;
	}

	public static String DeviceRemoteSetCalibration(String MN, String PW, String calibrationCommandStr) {
		String[] arr = calibrationCommandStr.split(";");
		String PolId = arr[0];
		String registerStartAddress = arr[1];
		String calibratingValue = arr[2];
		String QN = getQN();
		String responseData = "QN=" + QN + ";ST=32;CN=3032;PW=" + PW + ";MN=" + MN + ";Flag=5;CP=&&PolId=" + PolId + ",MB_BgnAddr=" + registerStartAddress + ",MB_Wrt=" + calibratingValue + "&&";
		int responseDataLength = responseData.length();
		DecimalFormat df = new DecimalFormat("0000");
		String responseDataLength4 = df.format(responseDataLength);
		String crc16 = crc16(responseData, responseData.length());
//		String crc16 = CrcUtil.CRC16_212(responseData.getBytes());
		if (crc16.length() < 4) {
			crc16 = String.format("%4s", crc16).replace(' ', '0');
		}
		String responseMsg = "##" + responseDataLength4 + responseData + crc16.toUpperCase() + "\r\n";
		log.info("远程校准命令：" + responseMsg);
		return responseMsg;
	}

	public static String relaySwitchControlResponse(String MN, String PW, String RlyNum, String RlyVal) {
		String QN = getQN();
		String responseData = "QN=" + QN + ";ST=27;CN=3050;PW=" + PW + ";MN=" + MN + ";Flag=5;CP=&&RlyNum=" + RlyNum + ",RlyVal=" + RlyVal + "&&";
		int responseDataLength = responseData.length();
		DecimalFormat df = new DecimalFormat("0000");
		String responseDataLength4 = df.format(responseDataLength);
		String crc16 = crc16(responseData, responseData.length());
//		String crc16 = CrcUtil.CRC16_212(responseData.getBytes());
		if (crc16.length() < 4) {
			crc16 = String.format("%4s", crc16).replace(' ', '0');
		}
		String responseMsg = "##" + responseDataLength4 + responseData + crc16.toUpperCase() + "\r\n";
		log.info("继电器控制命令：" + responseMsg);
		return responseMsg;
	}


}